use crate::core::base_node::NodeStatus;
use crate::core::action;
use core::base_node::{BaseNode, NodeData, TBaseNode, BLACKBOARD_REPEATER_LOOP};
use core::behavior_tree::NodeTypeRegister;
use std::collections::HashMap;
use core::tick::Tick;
use core::base_node::NodeStatus::{FAILURE, SUCCESS};

pub struct RepeatUntilFailure {
    base_node: NodeData<BaseNode>,
    child: Option<Box<TBaseNode>>,
    max_loop: i32
}
impl RepeatUntilFailure {
    fn new(config: serde_json::Value)->Result<RepeatUntilFailure, String> {
        match BaseNode::new(config) {
            Ok(_n) => {
                let max_loop_property = match _n.properties.get("maxLoop") {
                    Some(_ms) => {
                        match _ms.as_i64() {
                            Some(_ms_u) => {
                                _ms_u as i32
                            }
                            None => {
                                0
                            }
                        }
                    }
                    None => {
                        0
                    }
                };
                Ok(RepeatUntilFailure {
                    base_node: NodeData::new(_n),
                    child: None,
                    max_loop: max_loop_property
                })
            }
            Err(_e) => {
                Err(_e)
            }
        }
    }
    pub fn register(container: &mut NodeTypeRegister, name: String) {
        container.register_type(name, Box::new(|config: serde_json::Value, nodes: &mut HashMap<String, Box<dyn TBaseNode>>| {
            match RepeatUntilFailure::new(config) {
                Ok(_n) => {
                    nodes.insert(_n.base_node.id.to_string(), Box::new(_n));
                }
                Err(_e) => {}
            };
        }));
    }
}
impl TBaseNode for RepeatUntilFailure {
    fn get_base_node_ref(&self) -> NodeData<BaseNode> {
        self.base_node.clone()
    }
    fn add_child(&mut self, child: Box<TBaseNode>) {
        self.child = Some(child)
    }
    fn execute(&self, tick: &mut Tick) -> NodeStatus {
        BaseNode::_execute(self.base_node.clone(), tick, self)
    }

    fn open(&self, tick: &mut Tick) {
        tick.blackboard.set(&*BLACKBOARD_REPEATER_LOOP,  json!(0), &tick.tree.id, &self.base_node.id);
    }
    fn tick(&self, tick: &mut Tick) -> NodeStatus {
        match &self.child {
            Some(_c) => {

                let mut loop_time = match tick.blackboard.get(&*BLACKBOARD_REPEATER_LOOP, &tick.tree.id, &self.base_node.id) {
                    Some(_j) => {
                        match _j.as_i64() {
                            Some(_t) => {
                                _t as i32
                            }
                            None => { 0 }
                        }
                    }
                    None => { 0 }
                };
                let mut  status = NodeStatus::ERROR;
                while self.max_loop < 0 || loop_time < self.max_loop {
                    status = _c.execute(tick);
                    if status == NodeStatus::SUCCESS {
                        loop_time = loop_time + 1;
                    } else {
                        break;
                    }
                }
                tick.blackboard.set(&*BLACKBOARD_REPEATER_LOOP,  json!(loop_time), &tick.tree.id, &self.base_node.id);
                status
            }
            None => {
                NodeStatus::ERROR
            }
        }
    }
}